/*
 * Copyright (C) 2012  Romain DUBOIS
 * 
 * This file is part of NeMoS - Network and Modular Software
 * 
 * NeMoS is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 * 
 * NeMoS is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with NeMoS.  If not, see <http://www.gnu.org/licenses/>.
 */
package nemos.swing.util;

import java.awt.Container;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.StringTokenizer;

import nemos.swing.IComponentFactory;

/**
 * AbstractComponentFactory : The abstract component factory implementation.
 * 
 * <p>
 * This abstract implementation does not handle dynamic properties and convert
 * the string parameters into a map. It is assumend that parameters have the
 * following format :
 * 
 * <pre>
 * param1 = value1, param2 = value2, param3 = value3, ...
 * </pre>
 * 
 * Whitespaces around delimiters are trimmed.
 * 
 * </p>
 * 
 * @param <T>
 *            The generated components type
 * 
 * @author Romain DUBOIS
 */
public abstract class AbstractComponentFactory<T extends Container> implements IComponentFactory {

    /** The pairs delimiter in String parameter format */
    public static final String PAIR_DELIMITER = ","; //$NON-NLS-1$
    /** The name/value delimiter in String parameter format */
    public static final String VALUE_DELIMITER = "="; //$NON-NLS-1$
    /** The key for the whole String String parameter in the parameter map */
    public static final String RAW_PARAMETER_KEY = ""; //$NON-NLS-1$

    /** The generated components type */
    private final Class<T> mType;

    /**
     * Constructor.
     * 
     * @param pType
     *            The generated components type
     */
    protected AbstractComponentFactory(final Class<T> pType) {
        super();
        mType = pType;
    }

    /**
     * {@inheritDoc}
     * 
     * @see nemos.swing.IComponentFactory#createComponent()
     */
    @Override
    public T createComponent() {
        return createComponent(Collections.<String, Object> emptyMap());
    }

    /**
     * {@inheritDoc}
     * 
     * @see nemos.swing.IComponentFactory#createComponent(java.lang.String)
     */
    @Override
    public T createComponent(final String pInitParams) {
        final Map<String, Object> lParams = new HashMap<String, Object>();
        final List<String> lRawParams = new ArrayList<String>();

        final StringTokenizer lTokenizer = new StringTokenizer(pInitParams, PAIR_DELIMITER);
        while (lTokenizer.hasMoreTokens()) {
            final String lToken = lTokenizer.nextToken();
            lRawParams.add(lToken.trim());

            final String[] lParts = lToken.split(VALUE_DELIMITER);
            if (lParts.length == 2) {
                lParams.put(lParts[0].trim(), lParts[1].trim());
            }
        }
        lParams.put(RAW_PARAMETER_KEY, lRawParams);
        return createComponent(lParams);
    }

    /**
     * {@inheritDoc}
     * 
     * @see nemos.swing.IComponentFactory#createComponent(java.util.Map)
     */
    @Override
    public abstract T createComponent(Map<String, ?> pInitParams);

    /**
     * {@inheritDoc}
     * 
     * @see nemos.swing.IComponentFactory#getType()
     */
    @Override
    public Class<T> getType() {
        return mType;
    }

    /**
     * {@inheritDoc}
     * 
     * @see nemos.swing.IComponentFactory#getProperty(java.lang.String,
     *      java.awt.Container)
     */
    @SuppressWarnings("unused")
    @Override
    public Object getProperty(final String pProperty, final Container pComponent) {
        throw new UnsupportedOperationException();
    }

    /**
     * {@inheritDoc}
     * 
     * @see nemos.swing.IComponentFactory#getPropertyNames()
     */
    @Override
    public Set<String> getPropertyNames() {
        throw new UnsupportedOperationException();
    }

    /**
     * {@inheritDoc}
     * 
     * @see nemos.swing.IComponentFactory#getPropertyType(java.lang.String)
     */
    @SuppressWarnings("unused")
    @Override
    public Class<?> getPropertyType(final String pProperty) {
        throw new UnsupportedOperationException();
    }

    /**
     * {@inheritDoc}
     * 
     * @see nemos.swing.IComponentFactory#handleDynamicProperties()
     */
    @Override
    public boolean handleDynamicProperties() {
        return false;
    }

    /**
     * {@inheritDoc}
     * 
     * @see nemos.swing.IComponentFactory#setProperty(java.lang.String,
     *      java.lang.Object, java.awt.Container)
     */
    @SuppressWarnings("unused")
    @Override
    public void setProperty(final String pProperty, final Object pValue, final Container pComponent)
            throws UnsupportedOperationException {
        throw new UnsupportedOperationException();
    }
}
